home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / program / wdj0797.zip / SDKANN.ZIP / SOURCE.ZIP / ANNTATER.C < prev    next >
C/C++ Source or Header  |  1997-01-09  |  38KB  |  1,231 lines

  1. #include <assert.h>
  2. #include <ctype.h>
  3. #include "anntater.h"
  4. #include <windowsx.h>
  5. #include <commdlg.h>
  6. #include <dir.h>
  7. #include <direct.h>
  8.  
  9. #include <stdlib.h>
  10. #include <string.h>
  11.  
  12. #if defined(__WIN32__) || defined(__WIN32)
  13. #   define GetWindowParent(hwnd) ((HWND)GetWindowLong(hwnd, GWL_HWNDPARENT))
  14. #else
  15. #   define GetWindowParent(hwnd) ((HWND)GetWindowWord(hwnd, GWW_HWNDPARENT))
  16. #endif
  17.  
  18.  
  19. extern void InitCheckList(HINSTANCE);
  20.  
  21. int     InCopy      = FALSE;
  22. int     StopLoop    = FALSE;
  23.  
  24. BOOL    EnableControl(HWND Dialog, int Id, int On)
  25.     {
  26.     HWND    Child = GetDlgItem(Dialog, Id);
  27.     if(Child != 0)
  28.         return EnableWindow(Child, On);
  29.     else
  30.         return FALSE;
  31.     }
  32.  
  33. void    MessagePump(int Time = 100)
  34.     {
  35.     DWORD   StartTime = GetTickCount();
  36.     MSG Msg;
  37. while((GetTickCount() - StartTime) < Time)
  38.     while(PeekMessage(&Msg, NULL, 0, 0, PM_NOREMOVE))
  39.         {
  40.         switch(Msg.message)
  41.             {
  42.             case    WM_KEYDOWN      :
  43.             case    WM_LBUTTONDOWN  :
  44.             case    WM_RBUTTONDOWN  :
  45.             case    WM_MBUTTONDOWN  :
  46.                 StopLoop    = TRUE;
  47.             }
  48.         GetMessage(&Msg, NULL, 0, 0);
  49.         DispatchMessage(&Msg);
  50.         }
  51.     }
  52.  
  53. LRESULT SendCommand(HWND Dialog, HWND Control, int Id, int Command)
  54.     {
  55.     LRESULT Result = TRUE;
  56. #if defined(__WIN32__) || defined(__WIN32)
  57.     Result  = SendMessage(Dialog, WM_COMMAND, MAKEWPARAM(Id, Command),
  58.         (LPARAM)Control);
  59. #else
  60.     Result  = SendMessage(Dialog, WM_COMMAND, (WPARAM)Id,
  61.         MAKELPARAM(Control, Command));
  62. #endif
  63.     return Result;
  64.     }
  65.  
  66. LRESULT PostCommand(HWND Dialog, HWND Control, int Id, int Command)
  67.     {
  68.     LRESULT Result = TRUE;
  69. #if defined(__WIN32__) || defined(__WIN32)
  70.     Result  = PostMessage(Dialog, WM_COMMAND, MAKEWPARAM(Id, Command),
  71.         (LPARAM)Control);
  72. #else
  73.     Result  = PostMessage(Dialog, WM_COMMAND, (WPARAM)Id,
  74.         MAKELPARAM(Control, Command));
  75. #endif
  76.     return Result;
  77.     }
  78.  
  79.  
  80.  
  81. int     PushButton(HWND Dialog, int ButtonId, int Post = FALSE)
  82.     {
  83.     int     Result  = FALSE;
  84.     HWND    Button  = GetDlgItem(Dialog, ButtonId);
  85.     if(Button)
  86.         {
  87.         if(Post)
  88.             {
  89.             PostCommand(Dialog, Button, ButtonId, BN_CLICKED);
  90.             MessagePump();
  91.             }
  92.         else
  93.             SendCommand(Dialog, Button, ButtonId, BN_CLICKED);
  94.         Result      = TRUE;
  95.         }
  96.     return Result;
  97.     }
  98.  
  99. typedef BOOL (WINAPI*SETFUNC)(HWND Window);
  100.  
  101. int     MakeActive(HWND Window)
  102.     {
  103. #if defined(__WIN32__) || defined(__WIN32)
  104. SetForegroundWindow(Window);
  105. #else
  106. #define USER() GetModuleHandle("USER")
  107.     static int Loaded = FALSE;
  108.     static SETFUNC SetForegroundWindow;
  109.     if(!Loaded)
  110.         {
  111.         SetForegroundWindow = (SETFUNC)GetProcAddress(USER(),"SetForegroundWindow");
  112.         Loaded  = TRUE;
  113.         }
  114.     if(SetForegroundWindow)
  115.         SetForegroundWindow(Window);
  116.     else
  117.         SetActiveWindow(Window);
  118. #endif
  119.     MessagePump(300);
  120.     return TRUE;
  121.     }
  122. char    SelectedFile[512];
  123.  
  124. // name of main dialog box
  125. #define MAIN_DLG   "MainDialog"
  126.  
  127. HINSTANCE CurrentInstance;  // often need global for this
  128.  
  129. /*  GetHelpDialog() - locate a dialog belonging to the help window
  130.  *
  131.  *  Sometimes we need to find one of WinHelp's dialog windows.
  132.  *  This function locates a top-level window whose parent is the
  133.  *  WinHelp window. You can also specify the Id of a child window,
  134.  *  in case you need to distinguish between two WinHelp dialogs.
  135.  */
  136. HWND    GetHelpDialog(int ChildId=0)
  137.     {
  138.     HWND    Help = FindWindow("MS_WINHELP", NULL);
  139.     HWND    Rover = GetDesktopWindow();
  140.     Rover   = GetWindow(Rover, GW_CHILD);
  141.     while(Rover)
  142.         {
  143.         HWND    Parent = GetWindowParent(Rover);
  144.         HWND    GrandParent = 0;
  145.         if(Parent)
  146.             GrandParent = GetWindowParent(Parent);
  147.         if(Parent == Help || GrandParent == Help)
  148.             {
  149.             if(!ChildId || GetDlgItem(Rover, ChildId))
  150.                 return Rover;
  151.             }
  152.         Rover   = GetWindow(Rover, GW_HWNDNEXT);
  153.         }
  154.     return 0;
  155.     }
  156.  
  157.  
  158. #include <io.h>
  159. int WDJ_PathFind(const char *InPath, const char *File,
  160.                                     char *OutPath, int Maxlen)
  161.     {
  162.     /* sanity check */
  163.     if(InPath && *InPath)
  164.         {
  165.         // for each directory in the path
  166.         while(*InPath)
  167.             {
  168.             char    Dir[256];
  169.             const char*Rover = strchr(InPath, ';');
  170.             int Len = Rover ? (Rover - InPath) : strlen(InPath);
  171.             memcpy(Dir, InPath, Len);
  172.             Dir[Len]    = '\0';
  173.             strcat(Dir, "\\");
  174.             strcat(Dir, File);
  175.             if(access(Dir, 0) != -1)
  176.                 {
  177.                 if(OutPath && Maxlen)
  178.                     {
  179.                     strcpy(OutPath, Dir);
  180.                     return TRUE;
  181.                     }
  182.                 }
  183.             InPath += Len+1;
  184.             }
  185.         }
  186.     return FALSE;
  187.     }
  188.  
  189. const char* GetPath()
  190.     {
  191. #if defined(__WIN32) || defined(__WIN32__)
  192.     static char Path[512];
  193.     GetEnvironmentVariable("Path", Path, sizeof(Path));
  194.     return Path;
  195. #else
  196.     const char* Env = GetDOSEnvironment();
  197.     while(Env && *Env)
  198.         {
  199.         if(!strncmp(Env, "PATH=", 5))
  200.             return Env + 5;
  201.         else
  202.             Env += strlen(Env)+1;
  203.         }
  204.     return 0;
  205. #endif
  206.     }
  207.  
  208. /*  FindHelpFile - user selected new .hlp, try to locate it
  209.  *
  210.  *  When the user picks a different .hlp to annotate, this
  211.  *  function tries to locate that .hlp file. First, it tries
  212.  *  the last known path for that .hlp file, which would be
  213.  *  recorded in the .ini file. If that fails, it then searches
  214.  *  the DOS environment path. If that fails, then all the other
  215.  *  buttons are disabled except for the one that lets the user
  216.  *  tell us where the .hlp file is.
  217.  */
  218. int  FindHelpFile(HWND Dialog, const char*File)
  219.     {
  220.     int     Result = TRUE;
  221.     char    Found[512];
  222.     GetPrivateProfileString("AnnTater", File, "", Found, sizeof(Found), "wdj.ini");
  223.  
  224.     // if not found in .ini file
  225.     if(Found[0] == '\0')
  226.         {
  227.         const char*Search = GetPath();
  228.         if(!WDJ_PathFind(Search, File, Found, sizeof(Found)))
  229.             Result  = FALSE;
  230.         }
  231.     if(Result == TRUE)
  232.         {
  233.         EnableControl(Dialog, ID_COPY, TRUE);
  234.         EnableControl(Dialog, ID_SELECTALL, TRUE);
  235.         SetDlgItemText(Dialog, ID_HELP_PATH, Found);
  236.         strcpy(SelectedFile, Found);
  237.         }
  238.     else
  239.         {
  240.         EnableControl(Dialog, ID_COPY, FALSE);
  241.         EnableControl(Dialog, ID_SELECTALL, FALSE);
  242.         SetDlgItemText(Dialog, ID_HELP_PATH,
  243.             "<press Locate button to specify path for this file>");
  244.         }
  245.     return Result;
  246.     }
  247.  
  248.  
  249. // load RCDATA resource, assumes string terminated by 2 NULLs
  250. int     GetResource(const char *Name, char *Buffer)
  251.     {
  252.     int     Len;
  253.     char   *Data;
  254.     HGLOBAL Handle;
  255.     HRSRC   Pos = FindResource(CurrentInstance, Name, RT_RCDATA);
  256.     if(Pos == NULL)
  257.         return FALSE;
  258.     Handle  = LoadResource(CurrentInstance, Pos);
  259.     Data    = (char *)LockResource(Handle);
  260.     for(Len=0; Data[Len] || Data[Len+1]; ++Len)
  261.         ;
  262.     memcpy(Buffer, Data, Len+1);
  263.     UnlockResource(Handle);
  264.     FreeResource(Handle);
  265.     return Len;
  266.     }
  267.  
  268. char*   StrDup(const char* S)
  269.     {
  270.     size_t  Len     = strlen(S) + 1;
  271.     char* Result    = new char[Len];
  272.     if(Result)
  273.         memcpy(Result, S, Len);
  274.     return Result;
  275.     }
  276.  
  277. int     IsHelp32 = FALSE;
  278.  
  279. int     InitHelpVersion()
  280.     {
  281.     size_t  Len;
  282.     HINSTANCE Inst;
  283.     char    Path[512];
  284.     HWND    Help = FindWindow("MS_WINHELP", NULL);
  285.     Inst = GetWindowInstance(Help);
  286.     Path[0] = '\0';
  287.     GetModuleFileName(Inst, Path, sizeof(Path));
  288.     Len = strlen(Path);
  289.     /* 32-bit module name is "WINHLP32.EXE" */
  290.     if(Len >= 12 && Path[Len-6] == '3' && Path[Len-5] == '2')
  291.         IsHelp32    = TRUE;
  292. //MessageBox(NULL, Path, IsHelp32?"WINHLP32":"WinHelp", MB_OK);
  293.  
  294.     return TRUE;
  295.     }
  296.  
  297. int     WDJ_EmptyClipboard(void)
  298.     {
  299.     HWND ClipWin = GetDesktopWindow(); /* any window will do */
  300.  
  301.     if(OpenClipboard(ClipWin))
  302.         {
  303.         EmptyClipboard();
  304.         CloseClipboard();
  305.         return TRUE;
  306.         }
  307.     return FALSE;
  308.     }
  309.  
  310. int     WDJ_SetClipboardText(char *Buffer)
  311.     {
  312.     int     Result = FALSE;
  313.     HWND ClipWin = GetDesktopWindow(); /* any window will do */
  314.  
  315.     if(OpenClipboard(ClipWin))
  316.         {
  317.         size_t   Len = strlen(Buffer) + 1;
  318.         HGLOBAL  ClipData = GlobalAlloc(GHND, Len);
  319.         if(ClipData != 0)
  320.             {
  321.             char    *P = (char*)GlobalLock(ClipData);
  322.             strcpy(P, Buffer);
  323.             GlobalUnlock(ClipData);
  324.             if(SetClipboardData(CF_TEXT, ClipData))
  325.                 Result  = TRUE;
  326.             }
  327.         CloseClipboard();
  328.         }
  329.  
  330.     return Result;
  331.     }
  332.  
  333. int     WDJ_GetClipboardText(char *Buffer, UINT MaxSize)
  334.     {
  335.     int     Result = FALSE;
  336.     HWND ClipWin = GetDesktopWindow(); /* any window will do */
  337.  
  338.     if(OpenClipboard(ClipWin))
  339.         {
  340.         HGLOBAL  ClipData;
  341.         ClipData    = (HGLOBAL)GetClipboardData(CF_TEXT);
  342.         if(ClipData != NULL)
  343.             {
  344.             char *P     = (char*)GlobalLock(ClipData);
  345.             if(P != 0)
  346.                 {
  347.                 UINT  Len   = strlen(P) + 1;
  348.                 if(MaxSize > 0)
  349.                     {
  350.                     if(MaxSize < Len)
  351.                         Len = MaxSize;
  352.                     if(Len > 0)
  353.                         memcpy(Buffer, P, Len-1);
  354.                     Buffer[Len] = '\0';
  355.                     }
  356.                 Result  = TRUE;
  357.                 }
  358.             GlobalUnlock(ClipData);
  359.             }
  360.         CloseClipboard();
  361.         }
  362.  
  363.     return Result;
  364.     }
  365.  
  366.  
  367.  
  368.  
  369. //*********************************************************
  370.  
  371. class TTopic
  372.     {
  373. public:
  374.     TTopic() : RsrcId_(0) {}
  375.    ~TTopic() {}
  376.     int     Load(HINSTANCE Inst, int TopicNum);
  377.     int     IsFor(const char*FileName);
  378.  
  379.     int     GetFile(char* Buffer, int Max)
  380.         { return GetIt(0, Buffer, Max); }
  381.     int     GetDisplayTitle(char* Buffer, int Max)
  382.         { return GetIt(1, Buffer, Max); }
  383.     int     GetKeyword(char* Buffer, int Max);
  384.     int     GetTitle(char* Buffer, int Max)
  385.         { return GetIt(3, Buffer, Max); }
  386.     int     GetText(char* Buffer, int Max)
  387.         { return GetIt(4, Buffer, Max); }
  388.     void    Clear() { RsrcId_ = 0; TopicNum_ = 0; }
  389. private:
  390.     int     GetIt(int Pos, char*Buffer, int Max);
  391.     HRSRC   RsrcId_;
  392.     int     TopicNum_;
  393.     };
  394.  
  395. TTopic   ThisTopic;
  396.  
  397. int TTopic::GetKeyword(char* Buffer, int Max)
  398.     {
  399.     *Buffer = '\0';
  400.     int Result= GetIt(2, Buffer, Max);
  401.     // chop off any MSDN-style search terms
  402.     char *Extra = strstr(Buffer, " AND");
  403.     if(Extra)
  404.         *Extra  = '\0';
  405.     return Result;
  406.     }
  407.  
  408. int     TTopic::Load(HINSTANCE Inst, int TopicId)
  409.     {
  410.     TopicNum_   = TopicId;
  411.     RsrcId_  = FindResource(Inst,
  412.         MAKEINTRESOURCE(TopicId), RT_RCDATA);
  413.     return RsrcId_ != NULL;
  414.     }
  415.  
  416. int     TTopic::IsFor(const char* FileName)
  417.     {
  418.     if(!RsrcId_)
  419.         return FALSE;
  420.     char    File[128];
  421.     GetFile(File, sizeof(File));
  422.     return !strcmpi(FileName, File);
  423.     }
  424.  
  425. int     TTopic::GetIt(int Pos, char* Out, int Max)
  426.     {
  427.     int Result = FALSE;
  428.     if(!RsrcId_)
  429.         return Result;
  430.     char*   Buffer = new char[1024*8];
  431.     if(Buffer)
  432.         {
  433.         if(GetResource(MAKEINTRESOURCE(TopicNum_), Buffer))
  434.             {
  435.             const char*Rover = Buffer;
  436.             while(Pos--)
  437.                 Rover = Rover + strlen(Rover)+1;
  438.             if(Out && Max > 0)
  439.                 {
  440.                 for(int i=0; i < Max && *Rover; ++i)
  441.                     *Out++  = *Rover++;
  442.                 *Out = '\0';
  443.                 Result  = TRUE;
  444.                 }
  445.             }
  446.         delete[] Buffer;
  447.         }
  448.     return Result;
  449.     }
  450.  
  451. //*********************************************************
  452.  
  453.  
  454.  
  455.  
  456. typedef BOOL (*DLGCMDHANDLER)(HWND Dialog, UINT Notify,
  457.                                int ControlId, HWND Control);
  458. BOOL    DialogCommand(DLGCMDHANDLER Handler, HWND Dialog,
  459.                                WPARAM Param1, LPARAM Param2)
  460.     {
  461.     UINT    Notify;
  462.     UINT    ControlId;
  463.     HWND    Control;
  464. #if defined(__WIN32__)
  465.     Notify      = HIWORD(Param1);
  466.     ControlId   = LOWORD(Param1);
  467.     Control     = (HWND)Param2;
  468. #else
  469.     Notify      = HIWORD(Param2);
  470.     ControlId   = Param1;
  471.     Control     = (HWND)LOWORD(Param2);
  472. #endif
  473.     return Handler(Dialog, Notify, (int)ControlId, Control);
  474.     }
  475.  
  476.  
  477. // FindHelp - locate a standalone helpfile window!
  478. HWND    FindHelp(void)
  479.     {
  480.     return FindWindow("MS_WINHELP", NULL);
  481.     }
  482.  
  483. int     LoadTitles(HWND Listbox, const char*File)
  484.     {
  485.     char    *Buffer = (char *)malloc(1024*16);
  486.     char    *Title  = Buffer;
  487.     SendMessage(Listbox, WM_SETREDRAW, 0, 0);
  488.     SendMessage(Listbox, LB_RESETCONTENT, 0, 0);
  489.     TTopic  Topic;
  490.  
  491.     for(int i=1; Topic.Load(CurrentInstance, i); ++i)
  492.         {
  493.         if(Topic.IsFor(File))
  494.             {
  495.             Topic.GetDisplayTitle(Title, 1024);
  496.             int Index = SendMessage(Listbox, LB_ADDSTRING, 0, (LPARAM)Title);
  497.             if(Index != CB_ERR)
  498.                 {
  499.                 ListBox_SetItemData(Listbox, Index, i);
  500.                 }
  501.             }
  502.         }
  503.     SendMessage(Listbox, WM_SETREDRAW, 1, 0);
  504.     free(Buffer);
  505.     return TRUE;
  506.     }
  507.  
  508.  
  509.  
  510. enum { CANCEL = 9, REPLACE = 10, APPEND = 11,
  511.        ASK = 12,   SKIP = 13 } Always=ASK;
  512.  
  513. #ifdef __BORLANDC__
  514. #   pragma  argsused
  515. #endif
  516. static BOOL OnClobberDialogCommand(HWND Dialog, UINT Notify,
  517.                                 int ControlId, HWND Control)
  518.     {
  519.     if(ControlId == IDCANCEL)
  520.         {
  521.         EndDialog(Dialog, Always = CANCEL);
  522.         return FALSE;
  523.         }
  524.     else if(ControlId == ID_SKIP)
  525.         {
  526.         EndDialog(Dialog, SKIP);
  527.         if(IsDlgButtonChecked(Dialog, ID_STOPASKING))
  528.             Always  = CANCEL;
  529.         return FALSE;
  530.         }
  531.     else if(ControlId == ID_REPLACE)
  532.         {
  533.         EndDialog(Dialog, REPLACE);
  534.         if(IsDlgButtonChecked(Dialog, ID_STOPASKING))
  535.             Always  = REPLACE;
  536.         }
  537.     else if(ControlId == ID_APPEND)
  538.         {
  539.         EndDialog(Dialog, APPEND);
  540.         if(IsDlgButtonChecked(Dialog, ID_STOPASKING))
  541.             Always  = APPEND;
  542.         }
  543.     return FALSE;
  544.     }
  545.  
  546.  
  547. BOOL CALLBACK __export ClobberDialog(HWND Dialog, UINT Message,
  548.                                WPARAM Param1, LPARAM Param2)
  549.     {
  550.     if(Message == WM_INITDIALOG)
  551.         {
  552.         return TRUE;
  553.         }
  554.     else if(Message == WM_COMMAND)
  555.         {
  556.         return DialogCommand(OnClobberDialogCommand,
  557.                              Dialog, Param1, Param2);
  558.         }
  559.     return FALSE; /* FALSE == we didn't process msg */
  560.     }
  561.  
  562. /*  MatchTopic32 - Handle partial match for 32-bit WinHelp
  563.  *  
  564.  *  When a given keyword does not uniquely identify a help topic,
  565.  *  this function gets called to attempt to locate the correct
  566.  *  topic.
  567.  */
  568. BOOL    MatchTopic32(HWND Dialog, HWND SearchDlg, const char*Title)
  569.     {
  570.     int Result  = TRUE;
  571.  
  572.     // first, see if it is the "Topics Found" dialog
  573.     if(GetDlgItem(SearchDlg, 0x6F))
  574.         {
  575.         /* it is the "Topics Found" dialog, so we have to
  576.          * search the listed topic titles for a match
  577.          */
  578.         HWND Topics = GetDlgItem(SearchDlg, 0x6F);
  579.         int Count   = ListBox_GetCount(Topics);
  580.         for(int i=0; i < Count; ++i)
  581.             {
  582.             char    Item[256];
  583.             memset(Item, 0, sizeof(Item));
  584.             ListBox_GetText(Topics, i, Item);
  585.             // if we found a match
  586.             if(!strcmpi(Item, Title))
  587.                 {
  588.                 // then select it and press display button
  589.                 ListBox_SetCurSel(Topics, i);
  590.                 PushButton(SearchDlg, 0x01, TRUE);
  591.                 return TRUE;
  592.                 }
  593.             }
  594.         // no match, have to fail
  595.         PushButton(Topics, IDCANCEL, TRUE);
  596.         return FALSE;
  597.         }
  598.     // now we have to see if we have a match
  599.     // push the "Display" button
  600.     PushButton(SearchDlg, 0x01, TRUE);
  601.     // at this point, either topics dialog or msg box will appear
  602.     int j;
  603.     for(j=0; j < 5; ++j)
  604.         {
  605.         if(GetHelpDialog(0x6F))
  606.             break;
  607.         else if(GetHelpDialog(0x0A))
  608.             break;
  609.         MessagePump(500);
  610.         }
  611.     if(j >= 5)
  612.         {
  613.         MessageBox(NULL, "Could not synch with WinHelp!", "AnnTater", MB_OK);
  614.         return FALSE;
  615.         }
  616.  
  617.     HWND MsgBox = GetHelpDialog(0x0A);
  618.     if(MsgBox)
  619.         {
  620. SetWindowText(Dialog, "error message box appeared");
  621.         // "The word you have typed is not in the index..."
  622.         MessagePump();
  623.         PushButton(MsgBox, IDCANCEL, TRUE);
  624.         MessagePump();
  625.         PushButton(SearchDlg, IDCANCEL, TRUE);
  626.         MessagePump();
  627.         return FALSE;
  628.         }
  629. SetWindowText(Dialog, "error message box did not appear");
  630.     // see if that produced a list of matches
  631.     HWND TopicsDlg = GetHelpDialog(0x6F);
  632.     // if no matches
  633.     if(!TopicsDlg)
  634.         {
  635.         HWND MsgBox = GetHelpDialog(0x0A);
  636.         if(MsgBox)
  637.             {
  638. SetWindowText(Dialog, "About to push button!");
  639.             MessagePump(3000);
  640.             PushButton(MsgBox, IDCANCEL, TRUE);
  641.             MessagePump();
  642. SetWindowText(Dialog, "pushed button!");
  643.             MessagePump(3000);
  644.             Result  = FALSE;
  645.             }
  646.         PushButton(SearchDlg, IDCANCEL);
  647.         MessagePump();
  648.         }
  649.     return Result;
  650.     }
  651.  
  652.  
  653. /*  MatchTopic16 - Handle partial match for 16-bit WinHelp
  654.  *  
  655.  *  When a given keyword does not uniquely identify a help topic,
  656.  *  this function gets called to attempt to locate the correct
  657.  *  topic.
  658.  */
  659. BOOL    MatchTopic16(HWND Dialog, HWND SearchDlg, const char* Title,
  660.             const char*Keyword)
  661.     {
  662.     /*
  663.      * It turns out that 16-bit WinHelp will not produce an
  664.      * error if you press the Search button and an incorrect
  665.      * keyword is displayed. Therefore, we have to be a little
  666.      * tricky to figure out if our keyword has an exact match.
  667.      * The keywords are displayed in a custom listbox, not a
  668.      * standard one, so I can't easily check the current selection.
  669.      * Instead, I first press the Show Topics button, and WinHelp
  670.      * responds by wiping out my keyword with the closest matching
  671.      * keyword. By checking the edit box to see if my keyword stays
  672.      * the same, I can tell whether I had an exact match or not...
  673.      */
  674.  
  675. SetWindowText(Dialog, "Push Show Topics button");
  676.     // Press Show Topics button
  677.     PushButton(SearchDlg, 0x74, TRUE);
  678.     HWND    Edit    = GetDlgItem(SearchDlg, 0x66);
  679.     if(!Edit)
  680.         {
  681.         MessageBox(Dialog, "Search dialog not in expected format!", "AnnTater", MB_OK);
  682.         PushButton(SearchDlg, IDCANCEL, TRUE);
  683.         return FALSE;
  684.         }
  685.     char    MatchKey[256];
  686.     SendMessage(Edit, WM_GETTEXT, 255, (LPARAM)MatchKey);
  687.  
  688.     // if no exact match for our keyword
  689.     if(strcmpi(MatchKey, Keyword))
  690.         {
  691.         SetWindowText(Dialog, "No exact match for keyword!");
  692.         PushButton(SearchDlg, IDCANCEL, TRUE);
  693.         return FALSE;
  694.         }
  695.     // See how many topics matched
  696.     HWND    Topics  = GetDlgItem(SearchDlg, 0x6F);
  697.     int     Count   = ListBox_GetCount(Topics);
  698.     // if multiple topics for this keyword
  699.     if(Count > 1)
  700.         {
  701.         for(int i=0; i < Count; ++i)
  702.             {
  703.             char    Item[256];
  704.             memset(Item, 0, sizeof(Item));
  705.             ListBox_GetText(Topics, i, Item);
  706.             // if we found a match
  707.             if(!strcmpi(Item, Title))
  708.                 {
  709.                 // then select it and press Goto button
  710.                 ListBox_SetCurSel(Topics, i);
  711.                 PushButton(SearchDlg, 115, TRUE);
  712.                 return TRUE;
  713.                 }
  714.             }
  715.         // no match, have to fail
  716.         PushButton(Topics, IDCANCEL, TRUE);
  717.         return FALSE;
  718.         }
  719.  
  720.     // now go to the topic...
  721.     PushButton(SearchDlg, 115, TRUE);
  722.     MessagePump();
  723.     return TRUE;
  724.     }
  725.  
  726. static int ShowTopic(HWND Dialog, int LbIndex)
  727.     {
  728. SetWindowText(Dialog, "enter ShowTopic()");
  729.     int     Result  = TRUE;
  730.     HWND    Help    = FindWindow("MS_WINHELP", 0);
  731. //    MakeActive(Dialog);
  732.     int Topic = 0x7FFF & (int)ListBox_GetItemData(
  733.         GetDlgItem(Dialog, ID_TOPICTITLES), LbIndex);
  734.     ThisTopic.Load(CurrentInstance, Topic);
  735.     char    Keyword[128];
  736.     ThisTopic.GetKeyword(Keyword, sizeof(Keyword));
  737.     char    Title[128];
  738.     ThisTopic.GetTitle(Title, sizeof(Title));
  739.     WinHelp(Dialog, SelectedFile, HELP_PARTIALKEY,
  740.                 (DWORD)Keyword);
  741.     MakeActive(Help);
  742.     // pick a control that would exist in the search dialog,
  743.     // but not in some random error dialog...
  744.     int     SearchId = IsHelp32 ? 0x407 : 116;
  745.     HWND    SearchDlg = GetHelpDialog(SearchId);
  746.  
  747.     /* if we are using 32-bit WinHelp, and if more than one
  748.      * topic matches this keyword, WinHelp displays a different
  749.      * dialog, the "Topics Found" dialog
  750.      */
  751.     if(!SearchDlg && IsHelp32)
  752.         {
  753.         MakeActive(Help);
  754.         SearchDlg   = GetHelpDialog(0x6F);
  755.         if(!SearchDlg)
  756.             {
  757.             MessagePump(500);
  758.             SearchDlg   = GetHelpDialog(0x6F);
  759.             }
  760.         }
  761.     // if some other dialog came up, assume it's an error!
  762.     if(!SearchDlg && GetHelpDialog())
  763.         {
  764.         MessageBox(NULL, IsHelp32
  765.             ?"Error in searching .hlp file! (32-bit WinHelp)"
  766.             : "Error in searching .hlp file!", "AnnTater", MB_OK);
  767.         // push cancel button and hope for the best.
  768.         PushButton(GetHelpDialog(), IDCANCEL, TRUE);
  769.         return -1;
  770.         }
  771.     // if no exact match, then search dialog will appear
  772.     if(SearchDlg)
  773.         {
  774.         if(IsHelp32)
  775.             {
  776. SetWindowText(Dialog, "calling MatchTopic32");
  777.             if(!MatchTopic32(Dialog, SearchDlg, Title))
  778.                 Result  = FALSE;
  779.             }
  780.         else
  781.             {
  782. SetWindowText(Dialog, "calling MatchTopic16");
  783.             if(!MatchTopic16(Dialog, SearchDlg, Title, Keyword))
  784.                 Result  = FALSE;
  785.             }
  786.         // if no match, then dismiss search dialog
  787.         if(Result == FALSE)
  788.             PushButton(SearchDlg, IDCANCEL, TRUE);
  789.         }
  790.  
  791.     MessagePump();
  792.     return Result;
  793.     }
  794.  
  795. void    DisplayItem(HWND Dialog, int Index)
  796.     {
  797.     int TopicNum = 0x7FFF & SendDlgItemMessage(Dialog,
  798.         ID_TOPICTITLES, LB_GETITEMDATA, Index, 0);
  799.     ThisTopic.Load(CurrentInstance, TopicNum);
  800.  
  801.     /* set edit control text */
  802.     SendDlgItemMessage(Dialog, ID_TOPICTEXT,
  803.             EM_SETSEL, 1, MAKELPARAM(0,-1));
  804.     char*Buffer = new char[8*1024];
  805.     if(Buffer)
  806.         {
  807.         Buffer[0]   = '\0';
  808.         ThisTopic.GetText(Buffer, 8*1024);
  809.         SendDlgItemMessage(Dialog, ID_TOPICTEXT, EM_REPLACESEL,
  810.             0, (LPARAM)Buffer);
  811.         ThisTopic.GetTitle(Buffer, 8*1024);
  812.         SetDlgItemText(Dialog, ID_TOPIC_TITLE, Buffer);
  813.         ThisTopic.GetKeyword(Buffer, 8*1024);
  814.         SetDlgItemText(Dialog, ID_TOPIC_KEYWORD, Buffer);
  815.         delete[] Buffer;
  816.         }
  817.     SendDlgItemMessage(Dialog, ID_TOPICTEXT, EM_SETSEL, 0, 0);
  818.     SendDlgItemMessage(Dialog, ID_TOPICTEXT, EM_LINESCROLL, 0,
  819.         MAKELPARAM(-255, 0));
  820.  
  821.     }
  822.  
  823. void    CheckItem(HWND Dialog, int Item)
  824.     {
  825.     HWND Listbox = GetDlgItem(Dialog, ID_TOPICTITLES);
  826.  
  827.     // add a checkmark to this item
  828.     int Old = ListBox_GetItemData(Listbox, Item);
  829.     ListBox_SetItemData(Listbox, Item, Old|0x8000);
  830.     // make sure it is not selected
  831.     ListBox_SetSel(Listbox, FALSE, Item);
  832.     ListBox_SetTopIndex(Listbox, (Item < 3) ? 0 : Item - 3);
  833.     // schedule a redraw
  834.     InvalidateRect(Listbox, NULL, FALSE);
  835.     }
  836.  
  837.  
  838.  
  839. static BOOL    CopySelections(HWND Dialog)
  840.     {
  841.     char   *Buffer, *Text;
  842.     LRESULT Count;
  843.     int    *Items, i;
  844. //    HWND    Help    = FindHelp();
  845.  
  846.     StopLoop    = FALSE;
  847.     Count       = SendDlgItemMessage(Dialog, ID_TOPICTITLES,
  848.                         LB_GETSELCOUNT, 0, 0);
  849.     if(Count == 0)
  850.         return FALSE;
  851.     Items   = (int *)malloc(sizeof(int *)*(int)Count);
  852.     if(!Items)
  853.         {
  854.         MessageBox(Dialog, "Out of memory!", "AnnTater", MB_OK);
  855.         return FALSE;
  856.         }
  857.     SendDlgItemMessage(Dialog, ID_TOPICTITLES,
  858.                        LB_GETSELITEMS, (WPARAM)Count, (LPARAM)Items);
  859.  
  860.     Buffer  = (char *)malloc(1024*16);
  861.     if(!Buffer)
  862.         {
  863.         MessageBox(Dialog, "Out of memory!", "AnnTater", MB_OK);
  864.         return FALSE;
  865.         }
  866.     Text    = (char *)malloc(1024*16);
  867.     if(!Text)
  868.         {
  869.         free(Buffer);
  870.         MessageBox(Dialog, "Out of memory!", "AnnTater", MB_OK);
  871.         return FALSE;
  872.         }
  873.     int j;
  874.     for(i= 0; i < Count && Always != CANCEL; ++i)
  875.         {
  876.         if(StopLoop)
  877.             break;
  878.         DisplayItem(Dialog, Items[i]);
  879.         int Status = ShowTopic(Dialog, Items[i]);
  880.         if(Status == FALSE)
  881.             continue;
  882.         else if(Status == -1)
  883.             break;
  884.         /* open annotation window */
  885.         WinHelp(Dialog, SelectedFile, HELP_COMMAND, (DWORD)"Annotate()");
  886.         WDJ_EmptyClipboard();
  887.         HWND AnnDlg = GetHelpDialog();
  888.         for(j=0; j < 2000 && !AnnDlg; ++j)
  889.             {
  890. SetWindowText(Dialog, "Waiting for annotation window");
  891.             MessagePump();
  892.             AnnDlg  = GetHelpDialog();
  893.             }
  894.         if(!AnnDlg)
  895.             {
  896.             MessageBox(NULL, "Could not open annotation window!", "AnnTater", MB_OK);
  897.             return FALSE;
  898.             }
  899. SetWindowText(Dialog, "Got annotation window");
  900.         MakeActive(AnnDlg);
  901.         HWND CopyButton = GetDlgItem(AnnDlg, 0x73);
  902.         for(j = 0; j < 2000 && !CopyButton; ++j)
  903.             {
  904.             MessagePump();
  905.             CopyButton  = GetDlgItem(AnnDlg, 0x73);
  906.             }
  907.         if(!CopyButton)
  908.             {
  909.             MessageBox(NULL, "Anntation window not in expected format!", "AnnTater", MB_OK);
  910.             return 0;
  911.             }
  912.         // read in annotation text
  913.         ThisTopic.GetText(Text, 1024*16);
  914.         Buffer[0]   = '\0';
  915.         /* if annotation already exists */
  916.         if(IsWindowEnabled(CopyButton))
  917.             {
  918.             WDJ_EmptyClipboard();
  919.             // make annotation dialog copy it to clipboard
  920.             PushButton(AnnDlg, 0x73, TRUE);
  921.  
  922. SetWindowText(Dialog, "Waiting for clipboard data");
  923.             while(!WDJ_GetClipboardText(Buffer, 1024*16))
  924.                 MessagePump();
  925. SetWindowText(Dialog, "Got clipboard data");
  926.             
  927.             if(strstr(Buffer, Text))
  928.                 {
  929.                 PushButton(AnnDlg, IDCANCEL, TRUE);
  930.                 CheckItem(Dialog, Items[i]);
  931.                 continue;
  932.                 }
  933.             int Result  = Always;
  934.             if(Always == ASK)
  935.                 {
  936.                 MakeActive(Dialog);
  937.                 Result = DialogBox(CurrentInstance, "Clobber",
  938.                                 AnnDlg, ClobberDialog);
  939. SetWindowText(Dialog, "back from helper dialog");
  940.                 }
  941.             if(Result == CANCEL || Result == SKIP)
  942.                 {
  943.                 PushButton(AnnDlg, IDCANCEL, TRUE);
  944.                 continue;
  945.                 }
  946.             else if(Result == APPEND)
  947.                 ;
  948.             else if(Result == REPLACE)
  949.                 Buffer[0]   = '\0';
  950.             }
  951.         strcat(Buffer, Text);
  952.         if(WDJ_SetClipboardText(Buffer))
  953.             {
  954.             MakeActive(AnnDlg);
  955.             // do copy from clipboard to annotation
  956.             PushButton(AnnDlg, 0x74, TRUE);
  957.             // do save of annotation
  958.             PushButton(AnnDlg, 0x01, TRUE);
  959.             MessagePump(500);
  960.             CheckItem(Dialog, Items[i]);
  961.             }
  962.         else
  963.             {
  964.             MessageBox(NULL, "Could not set clipboard text", "", MB_OK);
  965.             PushButton(AnnDlg, IDCANCEL, TRUE);
  966.             MessagePump(1000);
  967.             }
  968.         }
  969.     free(Text);
  970.     free(Items);
  971.     free(Buffer);
  972.     StopLoop    = FALSE;
  973.     return TRUE;
  974.     }
  975.  
  976.  
  977. HWND    WindowFromInstance(HINSTANCE Instance)
  978.     {
  979.     HWND Rover = GetWindow(GetDesktopWindow(), GW_CHILD);
  980.  
  981.     while(Rover)
  982.         {
  983.         if(Instance == (HINSTANCE)GetWindowInstance(Rover))
  984.             return Rover;
  985.         else
  986.             Rover   = GetWindow(Rover, GW_HWNDNEXT);
  987.         }
  988.  
  989.     return (HWND)0;
  990.     }
  991.  
  992. static void SetCurDir(const char* In)
  993.     {
  994.     char* BSlash, *FSlash, *Slash;
  995.     char Path[256];
  996.     strcpy(Path, In);
  997.     BSlash  = strrchr(Path, '\\');
  998.     FSlash  = strrchr(Path, '/');
  999.     if(BSlash)
  1000.         Slash   = BSlash;
  1001.     if(FSlash && !Slash)
  1002.         Slash   = FSlash;
  1003.     else if(FSlash && Slash && FSlash > Slash)
  1004.         Slash   = FSlash;
  1005.     if(Slash)
  1006.         {
  1007.         *Slash  = '\0';
  1008.         chdir(Path);
  1009.         if(Path[1] == ':')
  1010.             {
  1011.             int Drive = (toupper(Path[0]) - 'A')+1;
  1012.             if(Drive > 0 && Drive <= 26)
  1013.                 _chdrive(Drive);
  1014.             }
  1015.         }
  1016.     }
  1017.  
  1018.  
  1019. static BOOL OnMainDialogCommand(HWND Dialog, UINT Notify,
  1020.                                 int ControlId, HWND Control)
  1021.     {
  1022.     if(ControlId == IDOK || ControlId == IDCANCEL)
  1023.         {
  1024.         EndDialog(Dialog, ControlId == IDOK);
  1025.         return FALSE;
  1026.         }
  1027.     else if(ControlId == ID_HELP && Notify == BN_CLICKED)
  1028.         {
  1029.         static char*Help =
  1030. "AnnTater: The Windows Developer's Journal helpfile annotater.\r\n"
  1031. "Use at your own risk!\r\n\r\n"
  1032. "First, select the type of helpfile you want to annotate. "
  1033. "If AnnTater cannot locate the file, press the Locate button "
  1034. "to specify where it resides. Next, select one or more "
  1035. "annotations (or press the Select All button). Finally, "
  1036. "press Copy to install your selections in the help file "
  1037. "(then stand well back). You may want to back up your "
  1038. ".ann file before starting this process. ";
  1039.         MessageBox(Dialog, Help, "AnnTater", MB_OK);
  1040.         }
  1041.     else if(ControlId == ID_FIND_FILE && Notify == BN_CLICKED)
  1042.         {
  1043.         HWND    Combo = GetDlgItem(Dialog, ID_FILES);
  1044.         char    File[256];
  1045.         char    Key[128];
  1046.         int Index = ComboBox_GetCurSel(Combo);
  1047.         strcpy(File,
  1048.             (const char*)ComboBox_GetItemData(Combo, Index)
  1049.             );
  1050.         strcpy(Key, File);
  1051.         
  1052.         OPENFILENAME    DialogArgs;
  1053.  
  1054.         memset(&DialogArgs, 0, sizeof(DialogArgs));
  1055.         DialogArgs.lStructSize  = sizeof(DialogArgs);
  1056.         DialogArgs.hwndOwner    = Dialog;
  1057.         char    Filter[256];
  1058.         memset(Filter, 0, sizeof(Filter));
  1059.         strcpy(Filter, "Selected help file");
  1060.         strcpy(Filter+strlen(Filter)+1, File);
  1061.         DialogArgs.lpstrFilter  = Filter;
  1062.         DialogArgs.nFilterIndex = 1;
  1063.         char    Title[256];
  1064.         wsprintf(Title, "Locate selected .hlp file (%s)", File);
  1065.         DialogArgs.lpstrTitle   = Title;
  1066.         DialogArgs.lpstrFile    = File;
  1067.         DialogArgs.nMaxFile     = 256;
  1068.         DialogArgs.Flags        = OFN_FILEMUSTEXIST | OFN_SHOWHELP;
  1069.  
  1070.         if(GetOpenFileName(&DialogArgs))
  1071.             {
  1072.             WritePrivateProfileString("AnnTater", Key, File, "wdj.ini");
  1073.             strcpy(SelectedFile, File);
  1074.             PostCommand(Dialog, GetDlgItem(Dialog, ID_FILES),
  1075.                 ID_FILES, CBN_SELCHANGE);
  1076.             }
  1077.         }
  1078.     else if(ControlId == ID_FILES && Notify == CBN_SELCHANGE)
  1079.         {
  1080.         char    File[256];
  1081.         File[0] = '\0';
  1082.         int Index = ComboBox_GetCurSel(Control);
  1083.         if(Index != CB_ERR)
  1084.             {
  1085.             strcpy(File, 
  1086.                 (const char*)ComboBox_GetItemData(Control, Index)
  1087.                 );
  1088.             // new .hlp file selected, attempt to set path
  1089.             if(!FindHelpFile(Dialog, File))
  1090.                 return TRUE;
  1091.             LoadTitles(GetDlgItem(Dialog, ID_TOPICTITLES), File);
  1092.             SetDlgItemText(Dialog, ID_TOPIC_KEYWORD,    "");
  1093.             SetDlgItemText(Dialog, ID_TOPIC_TITLE,      "");
  1094.             SetDlgItemText(Dialog, ID_TOPICTEXT,        "");
  1095.             WinHelp(Dialog, SelectedFile, HELP_QUIT, 0);
  1096.             MessagePump();
  1097. //            SetCurDir(SelectedFile);
  1098.             WinHelp(Dialog, SelectedFile, HELP_CONTENTS, 0);
  1099.             InitHelpVersion();
  1100.             MessagePump();
  1101.             MoveWindow(FindWindow("MS_WINHELP", NULL),
  1102.                 0, 0,
  1103.                 100 + GetSystemMetrics(SM_CXSCREEN)/3,
  1104.                 100 + GetSystemMetrics(SM_CYSCREEN)/3, TRUE);
  1105.             MakeActive(Dialog);
  1106.             }
  1107.         }
  1108.     else if(ControlId == ID_COPY)
  1109.         {
  1110.         Always = ASK;
  1111.         if(InCopy)
  1112.             {
  1113.             StopLoop    = TRUE;
  1114.             return TRUE;
  1115.             }
  1116.         InCopy  = TRUE;
  1117.         SetWindowText(Control, "Stop copy!");
  1118.         CopySelections(Dialog);
  1119.         SetWindowText(Control, "Copy");
  1120.         InCopy  = FALSE;
  1121.         SetWindowText(Dialog, "Windows Developer's Journal Annotater");
  1122.         MakeActive(Dialog);
  1123.         return FALSE;
  1124.         }
  1125.     else if(ControlId == ID_SELECTALL)
  1126.         {
  1127.         int Count = SendDlgItemMessage(Dialog, ID_TOPICTITLES,
  1128.                     LB_GETCOUNT, 0, 0);
  1129.         SendDlgItemMessage(Dialog, ID_TOPICTITLES, LB_SELITEMRANGE, 1,
  1130.             MAKELPARAM(0, Count-1));
  1131.         int Index = SendDlgItemMessage(Dialog, ID_TOPICTITLES,
  1132.                     LB_GETSELCOUNT, 0, 0);
  1133.         EnableControl(Dialog, ID_COPY,   Index != 0);
  1134.         return FALSE;
  1135.         }
  1136.     else if(ControlId == ID_TOPICTITLES)
  1137.         {
  1138.         /* if selection changes, update edit box */
  1139.         if(Notify == LBN_SELCHANGE)
  1140.             {
  1141.             LRESULT Index;
  1142.             /* enable/disable buttons, if we have selections or not */
  1143.             Index = SendDlgItemMessage(Dialog, ID_TOPICTITLES,
  1144.                         LB_GETSELCOUNT, 0, 0);
  1145.             EnableControl(Dialog, ID_COPY,   Index != 0);
  1146.  
  1147.             if(Index != 0)
  1148.                 {
  1149.                 /* load edit control with text from sel with caret */
  1150.                 Index = SendDlgItemMessage(Dialog, ID_TOPICTITLES,
  1151.                             LB_GETCARETINDEX, 0, 0L);
  1152.                 ShowTopic(Dialog, Index);
  1153.                 SetWindowText(Dialog, "Windows Developer's Journal Annotater");
  1154.                 DisplayItem(Dialog, Index);
  1155.                 MakeActive(Dialog);
  1156.                 }
  1157.             else
  1158.                 ThisTopic.Clear();
  1159.             }
  1160.         return TRUE;
  1161.         }
  1162.     return TRUE; /* TRUE == we didn't process the message */
  1163.     }
  1164.  
  1165. /* InitFileList - initialize combo-box of files.
  1166.  *
  1167.  *  Here we make a pass over all the annotations and
  1168.  *  form the list of the names of the files that are
  1169.  *  referred to by these annotations. The filenames
  1170.  *  are stored in a combobox.
  1171.  */
  1172. void    InitFileList(HWND Dialog, int ComboId)
  1173.     {
  1174.     HWND    Combo = GetDlgItem(Dialog, ComboId);
  1175.     int Index;
  1176. //    Index   = ComboBox_AddString(Combo, "MFC (mfc30.hlp)");
  1177. //    ComboBox_SetItemData(Combo, Index, "mfc30.hlp");
  1178.     Index   = ComboBox_AddString(Combo, "Win32 API (win32.hlp, api32.hlp)");
  1179.     ComboBox_SetItemData(Combo, Index, "win32.hlp");
  1180.     Index   = ComboBox_AddString(Combo, "Windows 3.1 API (win31wh.hlp)");
  1181.     ComboBox_SetItemData(Combo, Index, "win31wh.hlp");
  1182.     }
  1183.  
  1184. BOOL CALLBACK __export MainDialog(HWND Dialog, UINT Message,
  1185.                                WPARAM Param1, LPARAM Param2)
  1186.     {
  1187.     if(Message == WM_INITDIALOG)
  1188.         {
  1189.         EnableControl(Dialog, ID_COPY,      FALSE);
  1190.         EnableControl(Dialog, ID_SELECTALL, FALSE);
  1191.         InitFileList(Dialog, ID_FILES);
  1192.         ComboBox_SetCurSel(GetDlgItem(Dialog, ID_FILES), 0);
  1193.         PostCommand(Dialog, GetDlgItem(Dialog, ID_FILES),
  1194.             ID_FILES, CBN_SELCHANGE);
  1195.         return TRUE;
  1196.         }
  1197.     else if(Message == WM_TIMER)
  1198.         {
  1199.         MakeActive(Dialog);
  1200.         KillTimer(Dialog, 1);
  1201.         BringWindowToTop(Dialog);
  1202.         SetActiveWindow(Dialog);
  1203.         SetFocus(Dialog);
  1204.         }
  1205.     else if(Message == WM_USER + 999)
  1206.         {
  1207.         MakeActive(Dialog);
  1208.         }
  1209.     else if(Message == WM_COMMAND)
  1210.         {
  1211.         return DialogCommand(OnMainDialogCommand,
  1212.                              Dialog, Param1, Param2);
  1213.         }
  1214.     else if(Message == WM_DESTROY && SelectedFile[0])
  1215.         WinHelp(Dialog, SelectedFile, HELP_QUIT, 0);
  1216.     return FALSE; /* FALSE == we didn't process msg */
  1217.     }
  1218.  
  1219. #ifdef __BORLANDC__
  1220.     #pragma argsused
  1221. #endif
  1222. int WINAPI WinMain(HINSTANCE Instance, HINSTANCE Previous,
  1223.                    LPSTR CommandLine, int ShowCommand)
  1224.     {
  1225.     CurrentInstance    = Instance;
  1226.     InitCheckList(Instance);
  1227.     DialogBox(Instance, MAIN_DLG, NULL, MainDialog);
  1228.     return 0;
  1229.     }
  1230.  
  1231.